#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/time.h>
#include <asm/page.h>
#include <linux/timex.h>
#include <linux/rtc.h>

// NO.1
extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);

void print_current_time(char * timestamp)
{
    struct timespec64 txc;
    struct rtc_time tm;

    ktime_get_real_ts64(&(txc));

    printk("kes ktime_get_real_ts64 get %lld \n", txc.tv_sec);

    txc.tv_sec -= sys_tz.tz_minuteswest * 60;

    rtc_time_to_tm(txc.tv_sec, &tm);

    sprintf(timestamp, "[%d-%d-%d %d:%d:%d]",tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,tm.tm_hour, tm.tm_min, tm.tm_sec);
}

// NO.2
void get_timestamp(char *timestamp)
{
    struct timespec64 t;
    struct tm broken;

    /* get UTC time */
    ktime_get_real_ts64(&t);

    /* change to LOCAL time */
    t.tv_sec -= sys_tz.tz_minuteswest * 60;

    time64_to_tm(t.tv_sec, 0, &broken);
    broken.tm_year += 1900;
    broken.tm_mon++;

    sprintf(timestamp, " [%04ld-%02d-%02d %02d:%02d:%02d.%06ld] ",
            broken.tm_year, broken.tm_mon, broken.tm_mday, broken.tm_hour,
            broken.tm_min, broken.tm_sec, t.tv_nsec / 1000);

    printk("kes sec is [%lld] nsec is [%ld] \n",t.tv_sec, t.tv_nsec);
}


// main
int hello_init(void)
{
    char timestamp_buffer[32] = { 0 };
    char current_buffer[32] = { 0 };
    printk("hello gettime!\n");

    print_current_time(current_buffer);
    printk("kes print_current_time is [%s]\n", current_buffer);

    get_timestamp(timestamp_buffer);
    printk("kes get_timestamp is [%s]\n", timestamp_buffer);

    return 0;
}
 
void hello_exit(void)
{
    printk("Exit!\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("<libing@autelan.com>");
MODULE_DESCRIPTION("Kernel Exception Saver Module");

